package com.quectel.cms.controller.pay;

import com.google.common.base.Preconditions;
import com.quectel.business.common.util.sys.SysCodeUtils;
import com.quectel.business.pay.PayBusiness;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.interceptor.LoginUserSession;
import com.quectel.cms.util.SessionHolder;
import com.quectel.cms.vo.pay.OrderRefundAuditReq;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.constant.sys.SysCodeKeyConstants;
import com.quectel.core.module.village.dto.VillageDto;
import com.quectel.core.module.village.service.VillageService;
import com.quectel.pay.module.order.constants.OrderRefundConstants;
import com.quectel.pay.module.order.dto.PayOrderRefundDto;
import com.quectel.pay.module.order.service.PayOrderRefundService;
import com.quectel.pay.module.order.service.PayOrderService;
import com.quectel.util.common.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

import static com.quectel.constant.global.StatisticsConstants.TIME_RANGE_BY_DAY;

/**
 * 在这里编写说明
 *
 * @author: ryan
 * @email: ryan.ran@quectel.com
 * @date: 2023-05-26 14:34:00
 */
@RestController
@RequestMapping("payOrderRefund")
@Tag(name = "PayOrderRefundController", description = "支付中心退款账单相关api")

public class PayOrderRefundController extends BaseController {

    @DubboReference
    private PayOrderService payOrderService;
    @DubboReference
    private VillageService villageService;
    @DubboReference
    private PayOrderRefundService payOrderRefundService;
    @Autowired
    private PayBusiness payBusiness;

    @PostMapping("retry")
    public Response<Object> retry(@RequestBody Long refundOrderId){
        PayOrderRefundDto payOrderRefundDto = payOrderRefundService.selectById(refundOrderId);
        if (Objects.isNull(payOrderRefundDto)) {
            return Response.error("退款订单不存在");
        }
        if (!OrderRefundConstants.OrderRefundStatus.REFUNDING.getStatus().equals(payOrderRefundDto.getRefundStatus())) {
            return Response.error("只有退款中订单才能发起退款重试");
        }

        LoginUserSession sysUser = SessionHolder.getSysUser();
        Preconditions.checkNotNull(sysUser);

        Response<Object> refundResp = payBusiness.sendRefundRequest(payOrderRefundDto.getOutTradeNo()
                , payOrderRefundDto.getOutRefundNo(), payOrderRefundDto.getRefundAmount(), OrderRefundConstants.RefundType.PERSON.getType(), sysUser.getAccount());
        if (!refundResp.isSuccess()) {
            return Response.error("发起退款失败(总退款金额过大/订单超过退款期限),该退款永远无法发起退款,退款记录已被删除");
        }

        return Response.ok();
    }

    @PostMapping("audit")
    @RequirePermissions(values = "payOrderRefund:audit")
    public Response<Object> audit(@RequestBody @Validated OrderRefundAuditReq refundAuditReq){
        PayOrderRefundDto payOrderRefundDto = payOrderRefundService.selectById(refundAuditReq.getOrderRefundId());
        if (Objects.isNull(payOrderRefundDto)) {
            return Response.error("退款订单不存在");
        }
        if (!OrderRefundConstants.OrderRefundStatus.NOT_REFUND.getStatus().equals(payOrderRefundDto.getRefundStatus())) {
            return Response.error("只有待审核的订单才能发起审核");
        }
        if (OrderRefundConstants.RefundAuditStatus.APPROVED.getStatus().equals(payOrderRefundDto.getAuditStatus())) {
            return Response.error("审核通过的订单不允许再发起审核");
        }

        LoginUserSession sysUser = SessionHolder.getSysUser();
        Preconditions.checkNotNull(sysUser);

        if (OrderRefundConstants.RefundAuditStatus.APPROVED.getStatus().equals(refundAuditReq.getAuditStatus())) {
            // 通过
            Response<Object> refundResp = payBusiness.sendRefundRequest(payOrderRefundDto.getOutTradeNo()
                    , payOrderRefundDto.getOutRefundNo(), payOrderRefundDto.getRefundAmount(), OrderRefundConstants.RefundType.PERSON.getType(), sysUser.getAccount());
            if (!refundResp.isSuccess()) {
                return Response.error("发起退款失败(总退款金额过大/订单超过退款期限),该退款永远无法发起退款,退款记录已被删除");
            }
        } else if (OrderRefundConstants.RefundAuditStatus.NO_PASS.getStatus().equals(refundAuditReq.getAuditStatus())) {
            // 不通过
            PayOrderRefundDto updateObj = new PayOrderRefundDto();
            fillEditCommonData(updateObj);
            updateObj.setId(payOrderRefundDto.getId());
            updateObj.setAuditStatus(OrderRefundConstants.RefundAuditStatus.NO_PASS.getStatus());
            payOrderRefundService.updateById(updateObj);
        }
        return Response.ok();
    }


    /**
     * 列表
     */
    @GetMapping("exportExcel")
    @RequirePermissions(values = "payOrderRefund:exportExcel")
    public void exportExcel(@RequestParam Map<String, Object> params, HttpServletResponse httpServletResponse) {
        String[] headers = new String[]{"所属小区", "退款订单号", "商户订单号", "退款金额", "退款状态", "审核状态", "退款类型", "退款成功时间", "备注"};
        List<String[]> dataList = new ArrayList<>();

        if (params.containsKey(SystemConstants.TIME_SLOT_KEY_PAIR.getLeft())
                && params.containsKey(SystemConstants.TIME_SLOT_KEY_PAIR.getRight())
                && checkTimeRange(TIME_RANGE_BY_DAY, params.get(SystemConstants.TIME_SLOT_KEY_PAIR.getLeft()) + ""
                , params.get(SystemConstants.TIME_SLOT_KEY_PAIR.getRight()) + "", 32).isSuccess()) {
            super.fillAuthorityDataByRegionOrVillageInMemory(params);

            List<PayOrderRefundDto> result = new ArrayList<>();
            int pageNo = 0;
            params.put("limit", 1000);
            while (true) {
                params.put("offset", pageNo++ * 1000);
                List<PayOrderRefundDto> list = payOrderRefundService.queryList(params);
                if (CollectionUtils.isEmpty(list)) {
                    break;
                }
                result.addAll(list);
                if (list.size() < 1000) {
                    break;
                }
            }

            Map<Long, VillageDto> villageCacheMap = new HashMap<>();

            for (PayOrderRefundDto data : result) {
                VillageDto village = villageCacheMap.computeIfAbsent(data.getVillageId(), key -> villageService.selectCacheById(key));
                String[] item = new String[headers.length];
                item[0] = Objects.nonNull(village) ? village.getName() : "";
                item[1] = data.getOutRefundNo();
                item[2] = data.getOutTradeNo();
                item[3] = data.getRefundAmount().toPlainString();
                item[4] = SysCodeUtils.easyToGetName(SysCodeKeyConstants.REFUND_STATUS, data.getRefundStatus() + "");
                item[5] = SysCodeUtils.easyToGetName(SysCodeKeyConstants.REFUND_AUDIT_STATUS, data.getAuditStatus() + "");
                item[6] = SysCodeUtils.easyToGetName(SysCodeKeyConstants.REFUND_TYPE, data.getRefundType() + "");
                item[7] = DateUtils.format(data.getRefundSuccessTime(), DateUtils.FormatType.COMMON);
                item[8] = data.getRemark();
                dataList.add(item);
            }

            POIUtils.exportExcel(httpServletResponse, "退款账单信息", headers, dataList, "退款账单信息");
        }


    }

    /**
     * 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("list")
    @RequirePermissions(values = "payOrderRefund:list")
    @Operation(summary = "分页列表")
    public Response<Page<PayOrderRefundDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {

        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));
        Map<String, Object> params = request.getParams();

        if (params.containsKey(SystemConstants.TIME_SLOT_KEY_PAIR.getLeft())
                && params.containsKey(SystemConstants.TIME_SLOT_KEY_PAIR.getRight())
                && checkTimeRange(TIME_RANGE_BY_DAY, params.get(SystemConstants.TIME_SLOT_KEY_PAIR.getLeft()) + ""
                , params.get(SystemConstants.TIME_SLOT_KEY_PAIR.getRight()) + "", 32).isSuccess()) {
            super.fillAuthorityDataByRegionOrVillageInMemory(request.getParams());
            int total = payOrderRefundService.queryTotal(request.getParams());

            List<PayOrderRefundDto> list = null;
            if (total > 0) {
                list = payOrderRefundService.queryList(request.getParams());
            } else {
                list = new ArrayList<>();
            }

            for (PayOrderRefundDto payOrderDto : list) {
                VillageDto villageDto = villageService.selectCacheById(payOrderDto.getVillageId());
                if (Objects.nonNull(villageDto)) {
                    payOrderDto.setVillageName(villageDto.getName());
                }
            }

            Page<PayOrderRefundDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
            return Response.<Page<PayOrderRefundDto>>ok().wrap(page);
        }
        return Response.error("查询参数不正确");

    }

}
